<!DOCTYPE html>
<html lang="zh-CN">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>书籍数据分析平台</title>
  <!-- 先引入Vue 3核心库 -->
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>书籍数据分析平台</title>
  <!-- 先引入Vue 3核心库 -->
  <script src="https://unpkg.com/@vue/runtime-dom@3"></script>
  <script src="https://unpkg.com/vue@3"></script> <!-- 补充Vue核心库 -->
  <!-- 再引入Vue Router -->
  <script src="https://unpkg.com/vue-router@4"></script>
  <link rel="stylesheet" href="https://unpkg.com/element-plus@2.4.3/dist/index.css">
  <script src="https://unpkg.com/element-plus@2.4.3/dist/index.full.js"></script>

  <!-- 替换现有图标库CDN -->
  <script src="//unpkg.com/@element-plus/icons-vue"></script>
  <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/echarts@5.4.0/dist/echarts.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/echarts-wordcloud@2.1.0/dist/echarts-wordcloud.min.js"></script>
  <style>
    body {
      margin: 0;
      padding: 0;
      font-family: 'Helvetica Neue', Helvetica, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', Arial, sans-serif;
      background-color: #f5f7fa;
    }

    .app-container {
      display: flex;
      min-height: 100vh;
    }

    .sidebar {
      width: 220px;
      background: #304156;
      color: #fff;
      position: fixed;
      height: 100vh;
      overflow-y: auto;
    }

    .logo {
      padding: 20px;
      text-align: center;
      background: #233142;
      font-size: 18px;
      font-weight: bold;
    }

    .menu {
      padding: 0;
    }

    .menu-item {
      display: flex;
      align-items: center;
      padding: 12px 20px;
      cursor: pointer;
      transition: background-color 0.3s;
    }

    .menu-item:hover,
    .menu-item.active {
      background-color: #233142;
    }

    .menu-item i {
      width: 24px;
      text-align: center;
      margin-right: 10px;
    }

    .dashboard-container {
      flex: 1;
      margin-left: 220px;
      padding: 20px;
      overflow: auto;
    }

    .header {
      background: #fff;
      padding: 15px 20px;
      box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
      margin-bottom: 20px;
      display: flex;
      justify-content: space-between;
      align-items: center;
    }

    .page-title {
      font-size: 20px;
      font-weight: bold;
      display: flex;
      align-items: center;
      gap: 10px;
    }

    .card {
      background: #fff;
      border-radius: 8px;
      box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
      margin-bottom: 20px;
      padding: 20px;
    }

    .card-header {
      display: flex;
      justify-content: space-between;
      align-items: center;
      margin-bottom: 15px;
    }

    .card-title {
      font-size: 18px;
      font-weight: bold;
      display: flex;
      align-items: center;
      gap: 8px;
    }

    .chart-container {
      height: 350px;
      /* 统一高度 */
      width: 100%;
      margin: 0 auto 20px;
      border-radius: 4px;
      box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
    }

    .chart-loading {
      height: 350px;
      display: flex;
      align-items: center;
      justify-content: center;
      color: #909399;
    }

    .metrics-container {
      display: grid;
      grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
      gap: 20px;
    }

    .metric-card {
      background: #fff;
      border-radius: 8px;
      box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
      padding: 20px;
      display: flex;
      flex-direction: column;
      /* 添加过渡效果 */
      transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
    }

    /* 为三个卡片设置不同背景色 */
    .metrics-container .metric-card:nth-child(1) {
      background: linear-gradient(135deg, #f0f9ff 0%, #e6f7ff 100%);
      border-left: 4px solid #1890ff;
    }

    .metric-card:nth-child(2) {
      background: linear-gradient(135deg, #f6ffed 0%, #eaffd0 100%);
      border-left: 4px solid #52c41a;
    }

    .metric-card:nth-child(3) {
      background: linear-gradient(135deg, #fff7e6 0%, #fff1cc 100%);
      border-left: 4px solid #faad14;
    }

    /* 悬停效果增强 */
    .metric-card:hover {
      transform: translateY(-5px);
      box-shadow: 0 8px 16px rgba(0, 0, 0, 0.1);
      transform: translateY(-5px) scale(1.02);
    }

    /* 突出价格集中区间卡片 */
    .metric-card:nth-child(4) {
      background: linear-gradient(135deg, #e6f7ff 0%, #bae7ff 100%);
      border-left: 4px solid #f5222d;
      box-shadow: 0 4px 12px rgba(245, 34, 45, 0.1);
    }

    /* 悬停效果增强 */
    .price-analysis-card .metric-card:hover {
      transform: translateY(-5px) scale(1.02);
      box-shadow: 0 8px 16px rgba(0, 0, 0, 0.1);
    }

    .metric-title {
      font-size: 14px;
      color: #909399;
      margin-bottom: 10px;
    }

    .metric-value {
      font-size: 28px;
      font-weight: bold;
      margin-bottom: 10px;
    }

    .metric-desc {
      font-size: 13px;
      color: #606266;
    }

    .table-container {
      overflow-x: auto;
    }

    .loading {
      text-align: center;
      padding: 30px;
      color: #909399;
    }

    @media (max-width: 1024px) {
      .sidebar {
        width: 60px;
      }

      .sidebar .menu-item span {
        display: none;
      }

      .dashboard-container {
        margin-left: 60px;
      }

      .logo {
        font-size: 14px;
      }
    }

    @media (max-width: 768px) {
      .chart-container {
        height: 280px;
      }

      .metrics-container {
        grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
      }
    }
  </style>
</head>

<body>
  <div id="app">
    <el-config-provider :locale="zhCn">
      <div class="app-container">
        <div class="sidebar">
          <div class="logo">
            <el-icon>
              <Notebook />
            </el-icon>
            <span>书籍分析</span>
          </div>
          <ul class="menu">
            <li class="menu-item" :class="{ active: $route.path === '/overview' }" @click="goTo('/overview')">
              <el-icon>
                <Reading />
              </el-icon>
              <span>数据概览</span>
            </li>
            <li class="menu-item" :class="{ active: $route.path === '/comments' }" @click="goTo('/comments')">
              <el-icon>
                <Message />
              </el-icon>
              <span>评论分析</span>
            </li>
            <li class="menu-item" :class="{ active: $route.path === '/price' }" @click="goTo('/price')">
              <el-icon>
                <Money />
              </el-icon>
              <span>价格分析</span>
            </li>
            <li class="menu-item" :class="{ active: $route.path === '/publisher' }" @click="goTo('/publisher')">
              <el-icon>
                <Shop />
              </el-icon>
              <span>出版社分析</span>
            </li>
            <li class="menu-item" :class="{ active: $route.path === '/author' }" @click="goTo('/author')">
              <el-icon>
                <User />
              </el-icon>
              <span>作者分析</span>
            </li>
            <li class="menu-item" :class="{ active: $route.path === '/keywords' }" @click="goTo('/keywords')">
              <el-icon>
                <Search />
              </el-icon>
              <span>关键词分析</span>
            </li>
          </ul>
        </div>
        <div class="dashboard-container">
          <div class="header">
            <div class="page-title" :class="pageIcon && { 'with-icon': true }">
              <component :is="pageIcon" v-if="pageIcon" />
              <span>{{ pageTitle }}</span>
            </div>
            <el-button type="primary" @click="refreshData">
              <el-icon>
                <refresh />
              </el-icon>
              <span>刷新数据</span>
            </el-button>
          </div>
          <router-view v-slot="{ Component }">
            <component :is="Component" :key="$route.path" />
          </router-view>
        </div>
      </div>
    </el-config-provider>
  </div>

  <script>
    // 添加在script标签顶部
    const ChartUtils = {
      /**
       * 通用图表初始化函数
       * @param {string} containerSelector - 容器选择器
       * @param {Object} option - ECharts配置项
       * @returns {Object|null} - 图表实例或null
       */
      initChart(containerSelector, option) {
        try {
          // 检查容器是否存在
          const container = document.querySelector(containerSelector);
          if (!container) {
            console.error(`图表容器不存在: ${containerSelector}`);
            return null;
          }

          // 清空容器
          container.innerHTML = '';

          // 创建图表DOM元素
          const chartDom = document.createElement('div');
          chartDom.className = 'chart-container';
          container.appendChild(chartDom);

          // 初始化图表
          const chart = echarts.init(chartDom);
          chart.setOption(option);

          // 添加窗口大小调整事件
          window.addEventListener('resize', () => chart.resize());

          return chart;
        } catch (error) {
          console.error('图表初始化失败:', error);
          window.ElMessage.error('图表加载失败，请刷新页面重试');
          return null;
        }
      },

      /**
       * 销毁图表实例
       * @param {Object|null} chart - 图表实例
       */
      disposeChart(chart) {
        if (chart && chart.dispose) {
          chart.dispose();
        }
      }
    };

    // 中文语言包
    const zhCn = {
      name: 'zh-cn',
      el: {
        colorpicker: {
          confirm: '确定',
          cancel: '取消'
        },
        datepicker: {
          confirm: '确定',
          cancel: '取消',
          today: '今天'
        },
        pagination: {
          goto: '前往',
          pagesize: '条/页',
          total: '共 {total} 条',
          pageClassifier: ''
        },
        table: {
          emptyText: '暂无数据'
        }
      }
    };

    // 接口地址配置
    const API_BASE_URL = 'http://localhost:8000/api/analysis';

    // 导航组件
    const Navigation = {
      data() {
        return {
          routes: [
            { path: '/overview', name: '数据概览', icon: 'Reading' },
            { path: '/comments', name: '评论分析', icon: 'Message' },
            { path: '/price', name: '价格分析', icon: 'Money' },
            { path: '/publisher', name: '出版社分析', icon: 'Shop' },
            { path: '/author', name: '作者分析', icon: 'User' },
            { path: '/keywords', name: '关键词分析', icon: 'Search' }
          ]
        }
      },
      methods: {
        goTo(path) {
          this.$router.push(path);
        }
      }
    };

    // 数据概览页面
    const Overview = {
      data() {
        return {
          loading: true,
          totalBooks: 0,
          avgComments: 0,
          avgPrice: 0,
          totalPublishers: 0,
          top3Comments: [],
          priceDistribution: {},
          commentsChart: null,
          priceChart: null
        }
      },
      created() {
        this.fetchData();
      },
      beforeDestroy() {
        if (this.commentsChart) this.commentsChart.dispose();
        if (this.priceChart) this.priceChart.dispose();
      },
      methods: {
        fetchData() {
          this.loading = true;
          const requests = [
            axios.get(`${API_BASE_URL}/top3_comments`),
            axios.get(`${API_BASE_URL}/price_stats`),
            axios.get(`${API_BASE_URL}/price_distribution`),
            axios.get(`${API_BASE_URL}/publisher_impact`),
            axios.get(`${API_BASE_URL}/author_feedback`),
            axios.get(`${API_BASE_URL}/publisher_count`)
          ];

          Promise.all(requests)
            .then(responses => {
              // 处理评论数TOP3
              if (responses[0].data.status === 'success') {
                this.top3Comments = responses[0].data.data;
              }

              // 处理价格统计
              if (responses[1].data.status === 'success') {
                const priceStats = responses[1].data.data;
                console.log(priceStats);

                this.totalBooks = responses[4].data.data ? responses[4].data.data.length : 0;
                this.avgComments = priceStats.avg_comments || 3320;
                this.avgPrice = priceStats.average_price || 0;
              }

              // 处理价格分布
              if (responses[2].data.status === 'success') {
                this.priceDistribution = responses[2].data.data;
              }
              // 处理出版社总数
              if (responses[5].data.status === 'success') {
                this.totalPublishers = responses[5].data.data.total_publishers;
              }

              // 先设置 loading 为 false，确保 DOM 已渲染
              this.loading = false;

              // 使用 $nextTick 确保 DOM 更新后再初始化图表
              this.$nextTick(() => {
                this.initCharts();
              });
            })
            .catch(error => {
              console.error('获取数据失败', error);
              this.loading = false;
              window.ElMessage.error('获取数据失败，请重试');
            });
        },
        refreshData() {
          this.fetchData();
        },
        initCharts() {
          // 销毁已有图表实例
          ChartUtils.disposeChart(this.commentsChart);
          ChartUtils.disposeChart(this.priceChart);

          // 初始化评论图表
          if (this.top3Comments.length > 0) {
            this.commentsChart = ChartUtils.initChart('.comments-chart-container', {
              title: { text: '评论数TOP3书籍', left: 'center' },
              tooltip: { trigger: 'item', formatter: '{a} <br/>{b} : {c} 条' },
              xAxis: { data: this.top3Comments.map(item => item.title) },
              yAxis: { name: '评论数' },
              series: [{
                type: 'bar',
                data: this.top3Comments.map(item => item.comments),
                itemStyle: {
                  color: function (params) {
                    const colorList = ['#5470c6', '#91cc75', '#fac858'];
                    return colorList[params.dataIndex % colorList.length];
                  }
                },
                label: {
                  show: true,
                  position: 'top'
                }
              }]
            });
          }

          // 初始化价格分布图表
          if (Object.keys(this.priceDistribution).length > 0) {
            this.priceChart = ChartUtils.initChart('.price-chart-container', {
              title: { text: '价格区间分布', left: 'center' },
              tooltip: { trigger: 'item', formatter: '{a} <br/>{b} : {c} 本 ({d}%)' },
              series: [{
                name: '价格分布',
                type: 'pie',
                radius: '60%',
                center: ['50%', '60%'],
                data: Object.entries(this.priceDistribution).map(([range, { count, ratio }]) => ({
                  name: range,
                  value: count,
                  itemStyle: {
                    borderRadius: 6,
                    borderColor: '#fff',
                    borderWidth: 2
                  },
                  label: {
                    show: true,
                    formatter: '{b}: {c}本 ({d}%)'
                  }
                })),
                emphasis: {
                  itemStyle: {
                    shadowBlur: 10,
                    shadowOffsetX: 0,
                    shadowColor: 'rgba(0, 0, 0, 0.5)'
                  }
                }
              }]
            });
          }
        }
      },
      template: `
        <div v-if="!loading">
          <div class="card">
            <div class="card-header">
              <div class="card-title">
                <el-icon><Collection /></el-icon>
                <span>关键指标</span>
              </div>
            </div>
            <div class="metrics-container">
              <div class="metric-card">
                <div class="metric-title">书籍总数</div>
                <div class="metric-value">{{ totalBooks }}</div>
                <div class="metric-desc">平台收录的书籍数量</div>
              </div>
              <div class="metric-card">
                <div class="metric-title">平均评论数</div>
                <div class="metric-value">{{ avgComments.toFixed(0) }}</div>
                <div class="metric-desc">每本书的平均用户评论数</div>
              </div>
              <div class="metric-card">
                <div class="metric-title">平均价格</div>
                <div class="metric-value">¥{{ avgPrice.toFixed(2) }}</div>
                <div class="metric-desc">书籍的平均定价</div>
              </div>
              <div class="metric-card">
                <div class="metric-title">出版社总数</div>
                <div class="metric-value">{{ totalPublishers }}</div>
                <div class="metric-desc">平台合作的出版社数量</div>
              </div>
            </div>
          </div>
          
          <div class="card">
            <div class="card-header">
              <div class="card-title">
                <el-icon><Message /></el-icon>
                <span>评论数TOP3书籍</span>
              </div>
            </div>
            <!-- 添加加载状态 -->
            <div v-if="loading" class="chart-loading">
              <el-icon><Loading /></el-icon>
              <span>图表加载中...</span>
            </div>
            <div v-else class="comments-chart-container"></div>
            <div class="table-container">
              <el-table :data="top3Comments" style="width: 100%">
                <el-table-column prop="title" label="书名" width="300" />
                <el-table-column prop="author" label="作者" width="200" />
                <el-table-column prop="publisher" label="出版社" width="200" />
                <el-table-column prop="price" label="价格" width="100" :formatter="(row) => '¥' + row.price" />
                <el-table-column prop="comments" label="评论数" width="120" />
                <el-table-column prop="analysis" label="分析" />
              </el-table>
            </div>
          </div>
          
          <div class="card">
            <div class="card-header">
              <div class="card-title">
                <el-icon><Money /></el-icon>
                <span>价格分布分析</span>
              </div>
            </div>
            <div class="price-chart-container" style="width: 100%;"></div>
            <div class="table-container">
              <el-table :data="Object.entries(priceDistribution).map(([range, {count, ratio}]) => ({range, count, ratio}))" style="width: 100%">
                <el-table-column prop="range" label="价格区间" width="120" />
                <el-table-column prop="count" label="数量" width="100" />
                <el-table-column prop="ratio" label="占比" width="100" />
              </el-table>
            </div>
          </div>
        </div>
        <div class="loading" v-else>
          <el-icon><Loading /></el-icon>
          <span>加载数据中...</span>
        </div>
      `
    };

    // 评论分析页面
    const CommentsAnalysis = {
      data() {
        return {
          loading: true,
          top3Comments: [],
          commentsDistribution: null,
          commentsChart: null,
          commentsByPublisher: []
        }
      },
      created() {
        this.fetchData();
      },
      beforeDestroy() {
        if (this.commentsChart) this.commentsChart.dispose();
      },
      methods: {
        fetchData() {
          this.loading = true;
          axios.all([
            axios.get(`${API_BASE_URL}/top3_comments`),
            axios.get(`${API_BASE_URL}/publisher_impact`)
          ])
            .then(axios.spread((commentsRes, publisherRes) => {
              if (commentsRes.data.status === 'success') {
                this.top3Comments = commentsRes.data.data;
              }

              if (publisherRes.data.status === 'success') {
                this.commentsByPublisher = publisherRes.data.data.sort((a, b) => b.avg_comments - a.avg_comments).slice(0, 5);
                console.log(publisherRes.data);

              }

              this.loading = false;
              this.$nextTick(() => this.initCharts());
            }))
            .catch(error => {
              console.error('获取数据失败', error);
              this.loading = false;
              window.ElMessage.error('获取数据失败，请重试');
            });
        },
        refreshData() {
          this.fetchData();
        },
        initCharts() {
          ChartUtils.disposeChart(this.commentsChart);
          if (this.commentsByPublisher.length > 0) {
            this.commentsChart = ChartUtils.initChart('.comments-chart-container', {
              title: { text: '出版社平均评论数TOP5', left: 'center' },
              tooltip: { trigger: 'item', formatter: '{a} <br/>{b} : {c} 条' },
              xAxis: { data: this.commentsByPublisher.map(item => item.publisher) },
              yAxis: { name: '平均评论数' },
              series: [{
                type: 'bar',
                data: this.commentsByPublisher.map(item => item.avg_comments.toFixed(0)),
                itemStyle: {
                  color: function (params) {
                    const colorList = ['#5470c6', '#91cc75', '#fac858', '#ee6666', '#73c0de'];
                    return colorList[params.dataIndex % colorList.length];
                  }
                },
                label: {
                  show: true,
                  position: 'top'
                }
              }]
            });
          }
        }
      },
      template: `
        <div v-if="!loading">
          <div class="card">
            <div class="card-header">
              <div class="card-title">
                <el-icon><Message /></el-icon>
                <span>评论数TOP3书籍</span>
              </div>
            </div>
            <div class="table-container">
              <el-table :data="top3Comments" style="width: 100%">
                <el-table-column prop="title" label="书名" width="300" />
                <el-table-column prop="author" label="作者" width="200" />
                <el-table-column prop="publisher" label="出版社" width="200" />
                <el-table-column prop="price" label="价格" width="100" :formatter="(row) => '¥' + row.price" />
                <el-table-column prop="comments" label="评论数" width="120" />
                <el-table-column prop="analysis" label="分析" />
              </el-table>
            </div>
          </div>
          
          <div class="card">
            <div class="card-header">
              <div class="card-title">
                <el-icon><Brush /></el-icon>
                <span>出版社平均评论数TOP5</span>
              </div>
            </div>
            <div class="comments-chart-container" style="width: 100%;"></div>
            <div class="table-container">
              <el-table :data="commentsByPublisher" style="width: 100%">
                <el-table-column prop="publisher" label="出版社" width="200" />
                <el-table-column prop="book_count" label="书籍数量" width="120" />
                <el-table-column prop="avg_comments" label="平均评论数" width="120" :formatter="(row) => row.avg_comments.toFixed(0)"/>
                <el-table-column prop="avg_price" label="平均价格" width="120" :formatter="(row) => '¥' + row.avg_price.toFixed(2)" />
              </el-table>
            </div>
          </div>
        </div>
        <div class="loading" v-else>
          <el-icon><Loading /></el-icon>
          <span>加载数据中...</span>
        </div>
      `
    };

    // 价格分析页面
    const PriceAnalysis = {
      data() {
        return {
          loading: true,
          priceStats: null,
          priceDistribution: {},
          priceChart: null,
          priceByPublisher: []
        }
      },
      created() {
        this.fetchData();
      },
      beforeDestroy() {
        if (this.priceChart) this.priceChart.dispose();
      },
      methods: {
        fetchData() {
          this.loading = true;
          axios.all([
            axios.get(`${API_BASE_URL}/price_distribution`),
            axios.get(`${API_BASE_URL}/price_stats`),
            axios.get(`${API_BASE_URL}/publisher_impact`)
          ])
            .then(axios.spread((distributionRes, statsRes, publisherRes) => {
              if (distributionRes.data.status === 'success') {
                this.priceDistribution = distributionRes.data.data;
              }

              if (statsRes.data.status === 'success') {
                this.priceStats = statsRes.data.data;
              }

              if (publisherRes.data.status === 'success') {
                this.priceByPublisher = publisherRes.data.data.sort((a, b) => b.avg_price - a.avg_price).slice(0, 5);
              }

              this.loading = false;
              this.$nextTick(() => this.initCharts());
            }))
            .catch(error => {
              console.error('获取价格数据失败', error);
              this.loading = false;
              // 改进错误处理
              const errorMsg = error.response?.data?.message || '价格数据加载失败，请重试';
              window.ElMessage.error(errorMsg);
            });
        },
        refreshData() {
          this.fetchData();
        },
        initCharts() {
          // 销毁旧图表
          ChartUtils.disposeChart(this.priceChart);

          // 确保有数据且容器存在时才初始化图表
          if (Object.keys(this.priceDistribution).length > 0) {
            this.priceChart = ChartUtils.initChart('.price-chart-container', {
              title: { text: '书籍价格区间分布', left: 'center' },
              tooltip: { trigger: 'item', formatter: '{a} <br/>{b} : {c} 本 ({d}%)' },
              legend: { orient: 'vertical', left: 10, data: ['价格分布'] },
              series: [{
                name: '价格分布',
                type: 'pie',
                radius: ['40%', '70%'],
                avoidLabelOverlap: false,
                itemStyle: {
                  borderRadius: 10,
                  borderColor: '#fff',
                  borderWidth: 2
                },
                label: {
                  show: false,
                  position: 'center'
                },
                emphasis: {
                  label: {
                    show: true,
                    fontSize: 16,
                    fontWeight: 'bold'
                  }
                },
                labelLine: {
                  show: false
                },
                data: Object.entries(this.priceDistribution).map(([range, { count }]) => ({
                  name: range, value: count
                }))
              }]
            });
          }
        }
      },
      template: `
        <div v-if="!loading">
          <div class="card ">
            <div class="card-header">
              <div class="card-title">
                <el-icon><Money /></el-icon>
                <span>价格统计信息</span>
              </div>
            </div>
            <div class="metrics-container">
              <div class="metric-card">
                <div class="metric-title">平均价格</div>
                <div class="metric-value">¥{{ priceStats.average_price.toFixed(2) }}</div>
                <div class="metric-desc">所有书籍的平均定价</div>
              </div>
              <div class="metric-card">
                <div class="metric-title">价格中位数</div>
                <div class="metric-value">¥{{ priceStats.median_price.toFixed(2) }}</div>
                <div class="metric-desc">价格的中间值</div>
              </div>
              <div class="metric-card">
                <div class="metric-title">价格范围</div>
                <div class="metric-value">{{ priceStats.price_range }}</div>
                <div class="metric-desc">最低到最高价格</div>
              </div>
              <div class="metric-card">
                <div class="metric-title">价格集中区间</div>
                <div class="metric-value">{{ priceStats.price_concentration }}</div>
                <div class="metric-desc">大多数书籍的定价区间</div>
              </div>
            </div>
          </div>
          
          <div class="card">
            <div class="card-header">
              <div class="card-title">
                <el-icon><PieChart /></el-icon>
                <span>价格区间分布</span>
              </div>
            </div>
            <div class="price-chart-container" style="width: 100%;"></div>
            <div class="table-container">
              <el-table :data="Object.entries(priceDistribution).map(([range, {count, ratio}]) => ({range, count, ratio}))" style="width: 100%">
                <el-table-column prop="range" label="价格区间" width="120" />
                <el-table-column prop="count" label="数量" width="100" />
                <el-table-column prop="ratio" label="占比" width="100" />
              </el-table>
            </div>
          </div>
          
          <div class="card">
            <div class="card-header">
              <div class="card-title">
                <el-icon><Shop /></el-icon>
                <span>出版社平均价格TOP5</span>
              </div>
            </div>
            <div class="table-container">
              <el-table :data="priceByPublisher" style="width: 100%">
                <el-table-column prop="publisher" label="出版社" width="200" />
                <el-table-column prop="book_count" label="书籍数量" width="120" />
                <el-table-column prop="avg_price" label="平均价格" width="120" :formatter="(row) => '¥' + row.avg_price.toFixed(2)" />
                <el-table-column prop="avg_comments" label="平均评论数" width="120" />
              </el-table>
            </div>
          </div>
        </div>
        <div class="loading" v-else>
          <el-icon><Loading /></el-icon>
          <span>加载数据中...</span>
        </div>
      `
    };

    // 出版社分析页面
    const PublisherAnalysis = {
      data() {
        return {
          loading: true,
          publisherImpact: [],
          topPublishers: [],
          publisherChart: null
        }
      },
      created() {
        this.fetchData();
      },
      beforeDestroy() {
        if (this.publisherChart) this.publisherChart.dispose();
      },
      methods: {
        // 统一数据获取方法，与评论页面结构完全一致
        fetchData() {
          this.loading = true;
          axios.get(`${API_BASE_URL}/publisher_impact`)
            .then(response => {
              if (response.data.status === 'success') {
                this.publisherImpact = response.data.data;
                this.topPublishers = response.data.data.sort((a, b) => b.book_count - a.book_count).slice(0, 5);

              }
              this.loading = false;
              this.$nextTick(() => this.initCharts()); // 统一在数据加载后调用initCharts
            })
            .catch(error => {
              console.error('获取出版社数据失败', error);
              this.loading = false;
              window.ElMessage.error('获取数据失败，请重试');
            });
        },
        // 统一刷新方法
        refreshData() {
          this.fetchData();
        },
        // 统一图表初始化方法，与评论页面结构一致
        initCharts() {
          // 销毁已有图表实例
          ChartUtils.disposeChart(this.publisherChart);

          if (this.topPublishers.length > 0) {
            this.publisherChart = ChartUtils.initChart('.publisher-chart-container', {
              title: { text: '出版社书籍数量TOP5', left: 'center' },
              tooltip: { trigger: 'item', formatter: '{a} <br/>{b} : {c} 本' },
              xAxis: { data: this.topPublishers.map(item => item.publisher) },
              yAxis: { name: '书籍数量' },
              series: [{
                type: 'bar',
                name: '书籍数量',
                data: this.topPublishers.map(item => item.book_count),
                itemStyle: {
                  color: function (params) {
                    const colorList = ['#5470c6', '#91cc75', '#fac858', '#ee6666', '#73c0de'];
                    return colorList[params.dataIndex % colorList.length];
                  }
                },
                label: {
                  show: true,
                  position: 'top'
                }
              }]
            });
          }
        }
      },
      template: `
        <div v-if="!loading">
          <div class="card">
            <div class="card-header">
              <div class="card-title">
                <el-icon><Shop /></el-icon>
                <span>出版社影响力分析</span>
              </div>
            </div>
            <div class="publisher-chart-container" style="width: 100%;"></div>
            <div class="table-container">
              <el-table :data="publisherImpact" style="width: 100%">
                <el-table-column prop="publisher" label="出版社" width="200" />
                <el-table-column prop="book_count" label="书籍数量" width="120" />
                <el-table-column prop="avg_comments" label="平均评论数" width="120" />
                <el-table-column prop="avg_price" label="平均价格" width="120" :formatter="(row) => '¥' + row.avg_price.toFixed(2)" />
                <el-table-column prop="impact_analysis" label="影响力分析" />
              </el-table>
            </div>
          </div>
        </div>
        <div class="loading" v-else>
          <el-icon><Loading /></el-icon>
          <span>加载数据中...</span>
        </div>
      `
    };

    // 作者分析页面
    const AuthorAnalysis = {
      data() {
        return {
          loading: true,
          authorFeedback: [],
          topAuthors: [],
          authorChart: null
        }
      },
      created() {
        this.fetchData();
      },
      beforeDestroy() {
        if (this.authorChart) this.authorChart.dispose();
      },
      methods: {
        fetchData() {
          this.loading = true;
          axios.get(`${API_BASE_URL}/author_feedback`)
            .then(response => {
              if (response.data.status === 'success') {
                this.authorFeedback = response.data.data;
                this.topAuthors = response.data.data.sort((a, b) => b.avg_comments - a.avg_comments).slice(0, 5);
              }
              this.loading = false;
              this.$nextTick(() => this.initCharts()); // 统一在DOM更新后初始化图表
            })
            .catch(error => {
              console.error('获取作者数据失败', error);
              this.loading = false;
              window.ElMessage.error('获取数据失败，请重试');
            });
        },
        refreshData() {
          this.fetchData();
        },
        initCharts() {
          // 销毁已有图表实例
          ChartUtils.disposeChart(this.authorChart);

          if (this.topAuthors.length > 0) {
            this.authorChart = ChartUtils.initChart('.author-chart-container', {
              title: { text: '作者书籍数平均评论数TOP 5', left: 'center' },
              tooltip: { trigger: 'item', formatter: '{a} <br/>{b} : {c} 条' },
              xAxis: {
                // type: 'category',
                data: this.topAuthors.map(item => item.author),
                axisLabel: { rotate: 30, interval: 0 } // 处理名称过长问题
              },
              yAxis: { name: '平均评论数' },
              series: [{
                type: 'bar',
                data: this.topAuthors.map(item => item.avg_comments.toFixed(0)),
                itemStyle: {
                  color: function (params) {
                    const colorList = ['#5470c6', '#91cc75', '#fac858', '#ee6666', '#73c0de'];
                    return colorList[params.dataIndex % colorList.length];
                  }
                },
                label: {
                  show: true,
                  position: 'top'
                }
              }]
            });
          }
        }
      },
      template: `
        <div v-if="!loading">
          <div class="card">
            <div class="card-header">
              <div class="card-title">
                <el-icon><User /></el-icon>
                <span>作者与市场反馈分析</span>
              </div>
            </div>
            <div class="author-chart-container" style="width: 100%;"></div>
            <div class="table-container">
              <el-table :data="authorFeedback" style="width: 100%">
                <el-table-column prop="author" label="作者" width="200" />
                <el-table-column prop="book_count" label="书籍数量" width="120" />
                <el-table-column prop="avg_comments" label="平均评论数" width="120" :formatter="(row) => row.avg_comments.toFixed(0)"/>
                <el-table-column prop="avg_price" label="平均价格" width="120" :formatter="(row) => '¥' + row.avg_price.toFixed(2)" />
                <el-table-column prop="feedback_analysis" label="反馈分析" />
              </el-table>
            </div>
          </div>
        </div>
        <div class="loading" v-else>
          <el-icon><Loading /></el-icon>
          <span>加载数据中...</span>
        </div>
      `
    };

    // 关键词分析页面
    const KeywordsAnalysis = {
      data() {
        return {
          loading: true,
          titleKeywords: [],
          hotTopics: [],
          keywordsChart: null,
          outliers: []
        }
      },
      created() {
        this.fetchData();
      },
      beforeDestroy() {
        if (this.keywordsChart) this.keywordsChart.dispose();
      },
      methods: {
        fetchData() {
          this.loading = true;
          axios.all([
            axios.get(`${API_BASE_URL}/title_keywords`),
            axios.get(`${API_BASE_URL}/outliers`)
          ])
            .then(axios.spread((keywordsRes, outliersRes) => {
              if (keywordsRes.data.status === 'success') {
                this.titleKeywords = keywordsRes.data.data.top_keywords;
                this.hotTopics = keywordsRes.data.data.hot_topics;
              }

              if (outliersRes.data.status === 'success') {
                this.outliers = outliersRes.data.data.outliers;
              }

              this.loading = false;
              this.$nextTick(() => this.initCharts()); // 统一在DOM更新后初始化图表
            }))
            .catch(error => {
              console.error('获取关键词数据失败', error);
              this.loading = false;
              window.ElMessage.error('获取数据失败，请重试');
            });
        },
        refreshData() {
          this.fetchData();
        },
        initCharts() {
          // 销毁已有图表实例
          ChartUtils.disposeChart(this.keywordsChart);

          if (!this.titleKeywords || !Array.isArray(this.titleKeywords) || this.titleKeywords.length === 0) {
            console.warn('关键词数据为空或格式不正确');
            return;
          }
          const chartData = this.titleKeywords.map(item => {
            // 处理两种可能的数据格式: [keyword, count] 或 {keyword, count}
            if (Array.isArray(item)) {
              return { name: item[0], value: item[1] };
            } else if (typeof item === 'object') {
              return { name: item.keyword || item.name, value: item.count || item.value };
            }
            return null;
          }).filter(Boolean); // 过滤无效数据

          console.log(chartData);

          if (chartData.length > 0) {
            this.keywordsChart = ChartUtils.initChart('.keywords-chart-container', {
              title: { text: '书籍关键词频率分布', left: 'center' },
              tooltip: { trigger: 'item', formatter: '{b}: {c} 次' },
              series: [{
                type: 'wordCloud',
                gridSize: 20,
                sizeRange: [20, 60],
                rotationRange: [-30, 30],
                shape: 'circle',
                drawOutOfBound: true,
                // 添加颜色配置
                textStyle: {
                  color: function () {
                    // 使用HSV颜色空间，色调随机，饱和度和明度固定
                    return 'hsl(' + Math.random() * 360 + ', 70%, 60%)';
                  }
                },
                emphasis: {
                  textStyle: {
                    shadowBlur: 10,
                    shadowColor: '#333'
                  }
                },
                data: chartData
              }]
            });
          }
        }
      },
      template: `
        <div v-if="!loading">
          <div class="card">
            <div class="card-header">
              <div class="card-title">
                <el-icon><Search /></el-icon>
                <span>书名关键词分析</span>
              </div>
            </div>
            <div class="keywords-chart-container" style="width: 100%; height: 400px;"></div>
            <div class="table-container">
              <el-table :data="titleKeywords" style="width: 100%">
                <el-table-column prop="[0]" label="关键词" width="150" />
                <el-table-column prop="[1]" label="出现次数" width="100" />
              </el-table>
            </div>
            <div class="hot-topics" style="margin-top: 20px;">
              <el-tag v-for="(topic, index) in hotTopics" :key="index" type="success" size="large">{{ topic }}</el-tag>
            </div>
          </div>
          
          <div class="card">
            <div class="card-header">
              <div class="card-title">
                <el-icon><Failed /></el-icon>
                <span>异常值分析</span>
              </div>
            </div>
            <div class="table-container">
              <el-table :data="outliers" style="width: 100%">
                <el-table-column prop="title" label="书名" width="300" />
                <el-table-column prop="price" label="价格" width="100" :formatter="(row) => '¥' + row.price" />
                <el-table-column prop="comments" label="评论数" width="120" />
                <el-table-column prop="outlier_analysis" label="异常分析" />
              </el-table>
            </div>
          </div>
        </div>
        <div class="loading" v-else>
          <el-icon><Loading /></el-icon>
          <span>加载数据中...</span>
        </div>
      `
    };

    // 路由配置
    const router = VueRouter.createRouter({
      history: VueRouter.createWebHashHistory(),
      routes: [
        { path: '/', redirect: '/overview' },
        { path: '/overview', component: Overview, meta: { title: '数据概览', icon: 'Reading' } },
        { path: '/comments', component: CommentsAnalysis, meta: { title: '评论分析', icon: 'Message' } },
        { path: '/price', component: PriceAnalysis, meta: { title: '价格分析', icon: 'Money' } },
        { path: '/publisher', component: PublisherAnalysis, meta: { title: '出版社分析', icon: 'Shop' } },
        { path: '/author', component: AuthorAnalysis, meta: { title: '作者分析', icon: 'User' } },
        { path: '/keywords', component: KeywordsAnalysis, meta: { title: '关键词分析', icon: 'Search' } }
      ]
    });

    // 主应用
    const app = Vue.createApp({
      data() {
        return {
          zhCn: zhCn,
          pageTitle: '数据概览',
          pageIcon: null
        }
      },
      created() {
        router.afterEach((to, from) => {
          this.pageTitle = to.meta.title || '书籍数据分析平台';
          this.pageIcon = to.meta.icon ? `el-icon-${to.meta.icon}` : null;
        });
      },
      methods: {
        goTo(path) {
          this.$router.push(path);
        },
        refreshData() {
          window.ElMessage.info('数据刷新中...');
          // 触发当前页面的刷新
          const currentPath = this.$router.currentRoute.value.path;
          this.$router.push(currentPath).then(() => {
            // 路由跳转后，当前页面会重新加载数据
          });
        }
      }
    });

    for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
      app.component(key, component);
    }
    // 注册组件
    app.use(router);
    app.use(ElementPlus);
    app.mount('#app');
  </script>
</body>

</html>